package com.hjxr.xmgl.common;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hjxr.common.constant.Constants;
import com.hjxr.common.utils.StringUtils;
import com.hjxr.sysadmin.uitl.file.FileUploadUtils;
import com.hjxr.sysadmin.uitl.file.FileUtils;
import com.hjxr.common.config.BaseConfig;
import com.hjxr.framework.config.ServerConfig;
import com.hjxr.framework.web.domain.AjaxResult;
import com.hjxr.xmgl.utils.*;
import com.sun.org.apache.xpath.internal.operations.Bool;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 通用请求处理
 * @author ruoyi
 */
@RestController
@Api(tags = "通用请求处理")
public class CommonController {
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    @Autowired
    private ServerConfig serverConfig;

    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete   是否删除
     */
    @GetMapping("common/download")
    @ApiOperation("通用下载请求")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {

        System.out.println("------------------" + request);
        try {
            String validFilename = fileName.substring(fileName.lastIndexOf("/") + 1);
            if (!FileUtils.isValidFilename(validFilename)) {
                throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = BaseConfig.getDownloadPath() + fileName;

            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data;charset=UTF-8");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
            //httpServletResponse.setHeader("Content-Disposition", "attachment; filename="+  fileName);
            //response.setHeader("Content-Disposition", "attachment; filename="+  URLEncoder.encode(fileName,"UTF-8") );

            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete) {
                FileUtils.deleteFile(filePath);
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 通用上传请求
     */
    @PostMapping("/common/upload")
    @ApiOperation("通用上传请求")
    public AjaxResult uploadFile(MultipartFile file) throws Exception {
        try {
            // 上传文件路径
            String filePath = BaseConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;
            AjaxResult ajax = AjaxResult.success();
            int dirLastIndex = BaseConfig.getProfile().length() + 1;
            String currentDir = StringUtils.substring(filePath, dirLastIndex);
            int upLastIndex = currentDir.length() + 1;
            int preLastIndex = Constants.RESOURCE_PREFIX.length() + 1;
            ajax.put("fileName", StringUtils.substring(fileName, upLastIndex + preLastIndex));
            ajax.put("url", fileName);
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 本地资源通用下载
     */
    @GetMapping("/common/download/resource")
    @ApiOperation("本地资源通用下载")
    public void resourceDownload(String name, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 本地资源路径
        String localPath = BaseConfig.getProfile();
        // 数据库资源地址
        String downloadPath = localPath + StringUtils.substringAfter(name, Constants.RESOURCE_PREFIX);
        // 下载名称
        String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition",
                "attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName));
        FileUtils.writeBytes(downloadPath, response.getOutputStream());
    }


    @PostMapping("/common/excel")
    @ApiOperation("excel表格导入")
    public AjaxResult saveJson(@RequestBody String postData) throws IOException {
        boolean key = true;
        String msg = "";
        JSONObject Jobject = JSONObject.parseObject(postData);
        String jsonData = Jobject.toJSONString();
        Map<Boolean,String> map = verifity(jsonData); //验证excel字段以及模板

        for(Boolean k:map.keySet()){
            key = k;
            msg = map.get(k);
        }
        if(key == true){
            Random random = new Random();//创建random实例对象，程序中会用，用于产生随机数
            Tool tool = new Tool();//创建格式化json字符串工具类
            String path = BaseConfig.getUploadPath() + "/test.json";
            File file = new File(path);

            if (!file.exists())//判断文件是否存在，若不存在则新建
            {
                file.createNewFile();
            }
            FileOutputStream fileOutputStream = new FileOutputStream(file); //实例化FileOutputStream
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");//将字符流转换为字节流
            BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); //创建字符缓冲输出流对象

            String JsonString = tool.stringToJSON(jsonData);//将jsonarrray字符串格式化
            bufferedWriter.write(JsonString);//将格式化的jsonarray字符串写入文件
            bufferedWriter.flush();//清空缓冲区，强制输出数据
            bufferedWriter.close();//关闭输出流
            return AjaxResult.success();
        }else{
            return AjaxResult.error(msg);
        }

    }

    public HSSFWorkbook gexcel(String sheetName){
        // 上传文件路径
        String filePath = BaseConfig.getUploadPath();
        String path = filePath + "/test.json";
//        String path = "F:\\test.json";
        String s = readJsonFile(path);
        JSONObject jsonObject = JSONObject.parseObject(s);
        JSONArray jsonArray = jsonObject.getJSONArray("postData");

        String[][] content = new String[jsonArray.size()][13];


        for (int i = 0; i < jsonArray.size(); i++) {
            content[i] = new String[13];
            JSONObject key = (JSONObject) jsonArray.get(i);
            //与前台一致
            content[i][0] = key.get("zcfwsj").toString();
            content[i][1] = key.get("zcly").toString();
            content[i][2] = key.get("zcwh").toString();
            content[i][3] = key.get("cx").toString();
            content[i][4] = key.get("zcsyh").toString();
            content[i][5] = key.get("zcfbsj").toString();
            content[i][6] = key.get("zcnr").toString();
            content[i][7] = key.get("cxsj").toString();
            content[i][8] = key.get("zczt").toString();
            content[i][9] = key.get("zcmc").toString();
            content[i][10] = key.get("zclx").toString();
            content[i][11] = key.get("zhxgsj").toString();
            content[i][12] = key.get("zcjb").toString();
        }
        HSSFWorkbook wb = ExcelUtil.getHSSFWorkbook(sheetName, content, null);
        return wb;
    }

    @GetMapping("/common/exports")
    @ApiOperation("excel导出")
    public AjaxResult educe(HttpServletResponse response, HttpServletRequest request) throws IOException {
        String sheetName = "政策信息表";
        HSSFWorkbook wb = gexcel(sheetName); //构建excel表(后期可加不同参数获取不同的json文件)
        String filename = encodingFilename(sheetName);
        OutputStream out = null;
            try {
                //获取下载路径
                out = new FileOutputStream(getAbsoluteFile(filename));
                wb.write(out);
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return AjaxResult.success(filename);
        }

    public static String readJsonFile(String fileName) {
        String jsonStr = "";
        try {
            File jsonFile = new File(fileName);
            FileReader fileReader = new FileReader(jsonFile);
            Reader reader = new InputStreamReader(new FileInputStream(jsonFile), "utf-8");
            int ch = 0;
            StringBuffer sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @GetMapping("/common/read")
    @ApiOperation("读取json文件")
    public AjaxResult readJson() {
        try {
            String filePath = BaseConfig.getUploadPath();
            String path = filePath + "/test.json";
            String s = readJsonFile(path);
            JSONObject jsonObject = JSONObject.parseObject(s);
            JSONArray jsonArray = jsonObject.getJSONArray("postData");
            String jsonStr = jsonArray.toString();
            return AjaxResult.success(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error();
        }
    }


    @ApiOperation("读取上传的json文件")
    @RequestMapping(value = "/common/uploadFile", method = RequestMethod.POST)
    public AjaxResult uploadJson(@RequestParam(value="file",required = false) MultipartFile multipartFile) throws IOException {
        String jsonStr = "";
        InputStream inputStream = null;
        if (null != multipartFile) {
            inputStream = multipartFile.getInputStream();
            String s = IOUtils.toString(inputStream, "UTF-8");
//            String s = ReadFile((FileInputStream) inputStream);
            JSONObject Jobject = JSONObject.parseObject(s);
            String jsonData = Jobject.toJSONString();
            return AjaxResult.success(jsonData);
        }
        return AjaxResult.error("multipartFile为空");
    }


    public String ReadFile(FileInputStream fileInputStream) {

        BufferedReader reader = null;
        String laststr = "";
        try {

            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
            reader = new BufferedReader(inputStreamReader);
            String tempString = null;
            while ((tempString = reader.readLine()) != null) {

                laststr += tempString;
            }
            reader.close();
        } catch (IOException e) {

            e.printStackTrace();
        } finally {

            if (reader != null) {

                try {

                    reader.close();
                } catch (IOException e) {

                    e.printStackTrace();
                }
            }
        }
        return laststr;
    }


        //写在本地磁盘
    public void writeExcelToDisk(String filePath, HSSFWorkbook wb) {
        try {
            FileOutputStream fos = new FileOutputStream(filePath);
            wb.write(fos);
            fos.close();
            System.out.println("excel已经导出到:" + filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //发送响应方法
    public void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            try {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @GetMapping("/common/compress")
    @ApiOperation("压缩文件并下载")
    public AjaxResult pack(String str) throws Exception {

        String folderName ="襄阳市疾病预防控制中心迁建项目";
        String folderPath = getAbsoluteFile(folderName);
        File folder = new File(folderPath);
        OutputStream out;
        String dirName = null;
        String targetName = null;
        folder.mkdirs(); //新建文件夹
        if(str.equals("sjb")){
            String xlsName = "数据";
            String xlsPath = folderPath + "/" + xlsName;
            File xlsFolder = new File(xlsPath);
            xlsFolder.mkdirs();
            String sheetName = "政策信息表"; //xls表名
            String fileName = encodingFilename(sheetName); //文件名
            HSSFWorkbook wb = gexcel(sheetName);
            //输出流
            out = new FileOutputStream(xlsFolder + "/"+fileName);
            wb.write(out);
            out.close();

            dirName = folderPath;
            targetName = "襄阳市疾病预防控制中心迁建项目数据包.zip";
        }
        if(str.equals("fjzl")){
            String xlsName = "数据";
            String xlsPath = folderPath + "/" + xlsName;
            File xlsFolder = new File(xlsPath);
            xlsFolder.mkdirs();
            String attachName = "附件";
            String attachPath = folderPath + "/" + attachName;
            File attachFolder = new File(attachPath);
            attachFolder.mkdirs();
            String filePath = BaseConfig.getDownloadPath();
            String sourse = filePath + "数据包";
            sourse = FilePathUtil.getRealFilePath(sourse);
//            String sourse = "E:\\数据包";
            String target = attachPath;
            //克隆数据包
            Clone(sourse, target, sourse);
            String sheetName = "政策信息表"; //xls表名
            String fileName = encodingFilename(sheetName); //文件名
            HSSFWorkbook wb = gexcel(sheetName);

            //输出流
            out = new FileOutputStream(xlsFolder + "/"+fileName);
            wb.write(out);
            out.close();

            dirName = folderPath;
            targetName = "政府投资项目审计监督平台项目资料附件包.zip";
        }

        //获取本地保存路径
        String path = getAbsoluteFile(targetName);
        ZipUtil.zip(dirName,path);
        return AjaxResult.success(targetName);
    }

    public String getAbsoluteFile(String filename)
    {
        String downloadPath = BaseConfig.getDownloadPath() + filename;
        File desc = new File(downloadPath);
        if (!desc.getParentFile().exists())
        {
            desc.getParentFile().mkdirs();
        }
        return downloadPath;
    }

    public String encodingFilename(String filename)
    {
        filename = UUID.randomUUID().toString() + "_" + filename + ".xls";
        return filename;
    }

    /**
     *  根据路径删除指定的目录或文件，无论存在与否
     *@param sPath  要删除的目录或文件
     *@return 删除成功返回 true，否则返回 false。
     */
    @PostMapping("/common/delete")
    @ApiOperation("删除文件夹")
    public boolean DeleteFolder(@RequestBody String sPath) {
        //System.out.println("string---sPath-----" + sPath);
        JSONObject Jobject = JSONObject.parseObject(sPath);
        sPath = Jobject.getString("sPath");
        sPath = BaseConfig.getDownloadPath() + sPath;
        sPath = FilePathUtil.getRealFilePath(sPath);
        System.out.println("---------Path---------" + sPath);
        boolean flag = false;
        File file = new File(sPath);
        System.out.println("------------file------------" + file.toString());
        // 判断目录或文件是否存在
        if (!file.exists()) {  // 不存在返回 false
            return flag;
        } else {
            // 判断是否为文件
            if (file.isFile()) {  // 为文件时调用删除文件方法
                return deleteFile(sPath);
            } else {  // 为目录时调用删除目录方法
                return deleteDirectory(sPath);
            }
        }
    }
    /**
     * 删除单个文件
     * @param   sPath    被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public boolean deleteFile(String sPath) {
        boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }
    /**
     * 删除目录（文件夹）以及目录下的文件
     * @param   sPath 被删除目录的文件路径
     * @return  目录删除成功返回true，否则返回false
     */
    public boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        Boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) break;
            } //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    //拷贝文件夹
    public static void Clone(String url, String target, String sourse){
        //获取目录下所有文件
        File f = new File(url);
        File[] allf = f.listFiles();

        //遍历所有文件
        for(File fi:allf) {
            try {
                //拼接目标位置
                String URL = target+fi.getAbsolutePath().substring(sourse.length());

                //创建目录或文件
                if(fi.isDirectory()) {
                    Createflies(URL);
                }else {
                    fileInputOutput(fi.getAbsolutePath(),URL);
                }
                //递归调用
                if(fi.isDirectory()) {
                    Clone(fi.getAbsolutePath(), target, sourse);
                }
            }catch (Exception e) {
                System.out.println("error");
            }
        }
    }

    /**
     * 复制文件
     * @param sourse
     * @param target
     */
    public static void fileInputOutput(String sourse,String target) {
        try {
            File s = new File(sourse);
            File t = new File(target);

            FileInputStream fin = new FileInputStream(s);
            FileOutputStream fout = new FileOutputStream(t);

            byte[] a = new byte[1024*1024*4];
            int b = -1;

            //边读边写
            while((b = fin.read(a))!=-1) {
                fout.write(a,0,b);
            }

            fout.close();
            fin.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建目录
     * @param name
     * @return
     */
    public static boolean Createflies(String name) {
        boolean flag = false;
        File file=new File(name);
        //创建目录
        if(file.mkdir() == true){
            System.out.println("文件夹创建成功！");
            flag=true;
        }else {
            System.out.println("文件夹创建失败！");
            flag=false;
        }
        return flag;
    }
    //验证字段
    public Map<Boolean,String> verifity(String jsonData){
        Map<Boolean,String> map = new HashMap<>();
        Boolean flag = true;
        JSONObject jsonObject = JSONObject.parseObject(jsonData);
        JSONArray jsonArray = jsonObject.getJSONArray("postData");

        //判断标题是否符号标准
        if(!jsonArray.getJSONObject(0).getString("zcwh").equals("政策文号")){
            flag = false;
            map.put(flag,"政策文号字段不匹配！请修改导入的excel表！");
           return map;
        }
        if(!jsonArray.getJSONObject(0).get("cxsj").equals("撤销时间")){
            flag = false;
            map.put(flag,"撤销时间字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zcfwsj").equals("政策发文时间")){
            map.put(flag,"政策发文时间字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zcmc").equals("政策名称")){
            map.put(flag,"政策名称字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zclx").equals("政策类型")){
            map.put(flag,"政策类型字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zcly").equals("政策来源")){
            map.put(flag,"政策来源字段不匹配！请修改导入的excel表！");
            return map;
        }

        if(!jsonArray.getJSONObject(0).get("zcfbsj").equals("政策发布时间")){
            map.put(flag,"政策发布时间字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zhxgsj").equals("最后修改时间")){
            map.put(flag,"最后修改时间字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("cx").equals("是否撤销(1为否，0为是)")){
            map.put(flag,"是否撤销(1为否，0为是)字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zcnr").equals("政策内容")){
            map.put(flag,"政策内容字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zcfbsj").equals("政策发布时间")){
            map.put(flag,"政策发布时间字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zcjb").equals("政策级别")){
            map.put(flag,"政策级别字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zczt").equals("政策状态")){
            map.put(flag,"政策状态字段不匹配！请修改导入的excel表！");
            return map;
        }
        if(!jsonArray.getJSONObject(0).get("zcsyh").equals("政策索引号")){
            map.put(flag,"政策索引号字段不匹配！请修改导入的excel表！");
            return map;
        }

        for(int i = 1; i < jsonArray.size(); i++){
            //判断必填列不为空
            if(jsonArray.getJSONObject(i).get("zcwh").equals("") || jsonArray.getJSONObject(i).get("zcfwsj").equals("")|| jsonArray.getJSONObject(i).get("zcmc").equals("") || jsonArray.getJSONObject(i).get("zclx").equals("") || jsonArray.getJSONObject(i).get("zcly").equals("") || jsonArray.getJSONObject(i).get("zcfbsj").equals("") || jsonArray.getJSONObject(i).get("zhxgsj").equals("") || jsonArray.getJSONObject(i).get("zhxgsj").equals("") || jsonArray.getJSONObject(i).get("zcnr").equals("") || jsonArray.getJSONObject(i).get("zcjb").equals("") || jsonArray.getJSONObject(i).get("zczt").equals("")|| jsonArray.getJSONObject(i).get("zcsyh").equals("")){
                map.put(flag,"必填项不能为空！请修改导入的excel表！");
                return map;
            }
            //判断撤销列为1或0
            if(!jsonArray.getJSONObject(i).get("cx").equals("1") && !jsonArray.getJSONObject(i).get("cx").equals("0")){
                map.put(flag,"是否撤销字段只能填0或1！请修改导入的excel表！");
                return map;
            }
        }
        map.put(flag, "excel格式正确！");
        return map;
    }

    //文件目录下的子文件个数
    @PostMapping("common/fileNumber")
    @ApiOperation("统计目录")
    public AjaxResult fileNumber (@RequestBody String path){
        JSONObject Jobject = JSONObject.parseObject(path);
        path = Jobject.getString("path");
        System.out.println("-------------" + path);
        Map<String, Integer> fileMap = FileNumberUtil.fileNumber(path);
        int size = fileMap.size();
        int i = 0;
        String [][] content = new String[size][2];
        for (String key : fileMap.keySet()) {
            System.out.println("-------" + key + " " + fileMap.get(key));
            content[i][0] = key;
            content[i][1] = fileMap.get(key).toString();
            i++;
        }


        String sheetName =  "文件数量统计";
        HSSFWorkbook wb =  ExcelUtil.getHSSFWorkbook(sheetName, content, null);
        String filename = encodingFilename(sheetName);
        OutputStream out = null;
        try {
            //获取下载路径
            out = new FileOutputStream(getAbsoluteFile(filename));
            wb.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success(filename);
    }

}
